﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace OpenSearchTests
{
    [TestClass]
    public class NasaMirador
    {
        [TestMethod]
        [DeploymentItem("nasa_mirador_osdd.xml")]
        public void TestParseNasaMiradorOsddStream()
        {
            System.IO.FileStream stream = new System.IO.FileStream("nasa_mirador_osdd.xml", System.IO.FileMode.Open);
            OpenSearch.Osdd.OpenSearchDescriptionDocument osdd = new OpenSearch.Osdd.OpenSearchDescriptionDocument(stream);

            miradorCommon(osdd);
        }

        [TestMethod]
        [DeploymentItem("nasa_mirador_osdd.xml")]
        public void TestParseNasaMiradorOsddString()
        {
            string osddText = System.IO.File.ReadAllText("nasa_mirador_osdd.xml");
            OpenSearch.Osdd.OpenSearchDescriptionDocument osdd = new OpenSearch.Osdd.OpenSearchDescriptionDocument(osddText);

            miradorCommon(osdd);
        }

        private static void miradorCommon(OpenSearch.Osdd.OpenSearchDescriptionDocument osdd)
        {
            Assert.AreEqual("Mirador Dataset Search", osdd.ShortName);
            Assert.AreEqual("", osdd.LongName);
            Assert.AreEqual("Use Mirador Dataset Search to obtain a list of Earth Science Data Sets", osdd.Description);

            List<string> expectedTags = new List<string> { "Mirador", "Dataset", "Search" };
            Assert.IsTrue(expectedTags.SequenceEqual(osdd.Tags));

            Assert.AreEqual("gsfc-mirador-disc@lists.nasa.gov", osdd.Contact);

            List<OpenSearch.Osdd.Url> urls = osdd.Urls.ToList();
            Assert.AreEqual(2, urls.Count);
            OpenSearch.Osdd.Url url0 = urls[0];
            Assert.AreEqual(1, url0.IndexOffset);
            Assert.AreEqual("application/atom+xml", url0.MimeType);
            Assert.AreEqual("results", url0.Relation);
            Assert.AreEqual("http://mirador.gsfc.nasa.gov/cgi-bin/mirador/collectionlist.pl?keyword={searchTerms?}&page={startPage?}&count={count?}&osLocation={geo:box?}&osLocationPlaceName={geo:name?}&startTime={time:start?}&endTime={time:end?}&format=atom", url0.Template.ToString());
            OpenSearch.Template template0 = url0.Template;
            List<OpenSearch.TemplateParameter> template0parameters = template0.TemplateParameters.ToList<OpenSearch.TemplateParameter>();
            Assert.IsNotNull(template0parameters);
            Assert.AreEqual(8, template0parameters.Count);

            OpenSearch.TemplateParameter param0 = template0parameters[0];
            Assert.IsNotNull(param0);
            Assert.AreEqual("keyword", param0.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearch, param0.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("searchTerms", param0.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param0.Kind);

            OpenSearch.TemplateParameter param1 = template0parameters[1];
            Assert.IsNotNull(param1);
            Assert.AreEqual("page", param1.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearch, param1.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("startPage", param1.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param1.Kind);

            OpenSearch.TemplateParameter param2 = template0parameters[2];
            Assert.IsNotNull(param2);
            Assert.AreEqual("count", param2.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearch, param2.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("count", param2.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param2.Kind);

            OpenSearch.TemplateParameter param3 = template0parameters[3];
            Assert.IsNotNull(param3);
            Assert.AreEqual("osLocation", param3.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearchGeo, param3.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("box", param3.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param3.Kind);

            OpenSearch.TemplateParameter param4 = template0parameters[4];
            Assert.IsNotNull(param4);
            Assert.AreEqual("osLocationPlaceName", param4.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearchGeo, param4.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("name", param4.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param4.Kind);

            OpenSearch.TemplateParameter param5 = template0parameters[5];
            Assert.IsNotNull(param5);
            Assert.AreEqual("startTime", param5.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearchTime, param5.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("start", param5.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param5.Kind);

            OpenSearch.TemplateParameter param6 = template0parameters[6];
            Assert.IsNotNull(param6);
            Assert.AreEqual("endTime", param6.Name);
            Assert.AreEqual(OpenSearch.Constants.NSOpenSearchTime, param6.SubstitutionParameterValue.Namespace);
            Assert.AreEqual("end", param6.SubstitutionParameterValue.Parameter);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.OptionalSubstitution, param6.Kind);

            OpenSearch.TemplateParameter param7 = template0parameters[7];
            Assert.IsNotNull(param7);
            Assert.AreEqual("format", param7.Name);
            Assert.AreEqual(OpenSearch.TemplateParameterKind.Literal, param7.Kind);
            Assert.AreEqual("atom", param7.ParameterValue);

            OpenSearch.Osdd.Url url1 = urls[1];
            Assert.AreEqual("application/rss+xml", url1.MimeType);
            Assert.AreEqual("http://mirador.gsfc.nasa.gov/cgi-bin/mirador/collectionlist.pl?keyword={searchTerms}&page=1&count={count}&osLocation={geo:box}&startTime={time:start}&endTime={time:end}&format=rss", url1.Template.ToString());

            List<OpenSearch.Osdd.Image> images = osdd.Images.ToList();
            Assert.AreEqual(0, images.Count);

            List<OpenSearch.Query> queries = osdd.Queries.ToList<OpenSearch.Query>();
            Assert.AreEqual(2, queries.Count);
            OpenSearch.Query query0 = queries[0];
            Assert.AreEqual("example", query0.Role);
            Assert.AreEqual("ozone", query0.SearchTerms);
            Assert.AreEqual("Sample Bounding Box Search", query0.Title);
            Assert.AreEqual("2010-01-01", query0.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchTime, "start"));
            Assert.AreEqual("2010-01-10", query0.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchTime, "end"));
            Assert.AreEqual("-130.0,25.0,-65.0,50.0", query0.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchGeo, "box"));
            // Check for something not present
            Assert.IsNull(query0.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchRelevance, "foo"));
            Assert.IsNull(query0.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchRelevance, null));
            Assert.IsNull(query0.GetExtendedAttribute(null, "foo"));

            OpenSearch.Query query1 = queries[1];
            Assert.AreEqual("example", query1.Role);
            Assert.AreEqual("Surface Air Temperature", query1.SearchTerms);
            Assert.AreEqual("Sample PlaceName Search", query1.Title);
            Assert.AreEqual("2010-01-01", query1.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchTime, "start"));
            Assert.AreEqual("2010-01-10", query1.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchTime, "end"));
            Assert.AreEqual("greenbelt", query1.GetExtendedAttribute(OpenSearch.Constants.NSOpenSearchGeo, "name"));
        }

        [TestMethod]
        [DeploymentItem("mirador_rss_response.xml")]
        public void TestParseNasaMiradorRssString()
        {
            string responseText = System.IO.File.ReadAllText("mirador_rss_response.xml");
            OpenSearch.Response response = new OpenSearch.Response(responseText);

            Assert.IsNotNull(response);
            Assert.AreEqual("Mirador collection results for 'atmosphere'", response.Title);
            Assert.AreEqual(1, response.Links.Count);
            Assert.AreEqual(new Uri("http://mirador.gsfc.nasa.gov"), response.Links.ToList<OpenSearch.Link>()[0].Href);
            Assert.AreEqual("This is Earth Science data published by Mirador.", response.Description);
            Assert.AreEqual("en-us", response.Language);
            Assert.AreEqual("http://mirador.gsfc.nasa.gov/help", response.GetExtendedElements<string>("", "docs").ToList<string>()[0]);
            Assert.AreEqual("GES-DISC", response.Generator);
            Assert.AreEqual(1, response.Categories.Count);
            Assert.AreEqual("Data", response.Categories[0].Name);

            List<OpenSearch.ResponseItem> items = response.Items.ToList<OpenSearch.ResponseItem>();
            Assert.AreEqual(42, items.Count);
            OpenSearch.ResponseItem item1 = items[1];
            Assert.IsNotNull(item1);
            Assert.AreEqual("OSDD for: UARCL3AT.001", item1.Title);
            Assert.AreEqual(new Uri("http://mirador.gsfc.nasa.gov/OpenSearch/mirador_opensearch_UARCL3AT.001.xml"), item1.Links.ToList<OpenSearch.Link>()[0].Href);
            Assert.AreEqual("Granule Level OSDD for: UARCL3AT.001", item1.Summary);
            Assert.AreEqual(DateTime.Parse("1/1/1978").ToUniversalTime(), item1.Published);
        }

        [TestMethod]
        [DeploymentItem("mirador_atom_bad_dateformat.xml")]
        public void TestParseNasaMiradorAtomBadDateFormat()
        {
            string responseText = System.IO.File.ReadAllText("mirador_atom_bad_dateformat.xml");
            OpenSearch.Response response = new OpenSearch.Response(responseText);

            Assert.AreEqual("Mirador collection results for atmosphere", response.Title);
            Assert.AreEqual(new DateTimeOffset(2014, 03, 20, 22, 05, 28, 0, new TimeSpan(0)), response.LastUpdated);
            Assert.AreEqual("atmosphere (distributed by GES DISC)", response.Description);
            Assert.AreEqual(61, response.TotalResponseCount);
            Assert.AreEqual(1, response.StartIndex);
            Assert.AreEqual(41, response.Items.Count()); // manually hacked the XML to remove items.
            OpenSearch.ResponseItem item0 = response.Items.ToList<OpenSearch.ResponseItem>()[0];
            Assert.IsNotNull(item0);
            Assert.AreEqual("MERRA 2D IAU Diagnostic, Surface Fluxes, Monthly Mean (2/3x1/2L1) (MATMNXFLX) ", item0.Title);
            System.Collections.ObjectModel.Collection<System.ServiceModel.Syndication.SyndicationPerson> authors0 = item0.Authors;
            Assert.IsNotNull(authors0);
            Assert.AreEqual("GES DISC", authors0[0].Name);
            Assert.AreEqual("gsfc-mirador-disc@lists.nasa.gov", authors0[0].Email);
            Assert.AreEqual(new Uri("http://mirador.gsfc.nasa.gov/collections/MATMNXFLX__5.2.0.shtml"), item0.Id);
            Assert.AreEqual("DataSet:MATMNXFLX Avg Size:23.648 Temporal Resolution:29 Days Spatial Resolution: 1/2 Degrees x 2/3 degrees", item0.Content.Body);
        }
    }
}